<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>

    class Event {
      constructor() {
        // 保存所有事件及对应处理程序的对象
        this.listeners = {}
        // this.listeners.click = [fn1, fn2, fn3]
      }

      /**
       * 注册事件监听
       */
      on(name, callback) {
        // 如果在 listeners 中找不到已注册的事件监听器，则创建一个空数组
        if (!this.listeners[name]) {
          this.listeners[name] = []
        }
        // 将事件处理器（函数）保存起来
        this.listeners[name].push(callback)
      }

      /**
       * 移除事件监听
       */
      off(name, callback) {
        if (!this.listeners[name]) {
          throw new Error('还未注册事件监听')
        }

        // 有回调函数，则移除回调函数指定的处理器
        if (callback) {
          this.listeners[name] = this.listeners[name].filter(cb => cb !== callback)
          return
        }
        // 没有回调函数，则删除整个事件
        delete this.listeners[name]
      }

      /**
       * 触发事件
       */
      emit(name, ...args) {
        if (!this.listeners[name]) {
          throw new Error('还未注册事件监听')
        }
        this.listeners[name].forEach(cb => cb(...args))
      }
    }
  </script>

  <script>
    const event = new Event()
    function test3() {
      console.log('test33333')
    }
    event.on('test', function() {
      console.log('test111111')
    })
    event.on('test', function() {
      console.log('test222222')
    })
    event.on('test', test3)

    // 移除事件监听
    // event.off('test', test3)
    event.off('test')

    // 触发事件
    event.emit('test')
    // event.emit('demo')
  </script>
</body>
</html>